/**
 *It is a demo for practicing JAVA. All codes are opened source by Jian.
 */
package jian.tool.daocode.util;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * Dao代码生成
 * 
 * @author Jian
 * @date 2012-7-20
 * @version
 * 
 */
public class CodeDaoHelper {

	/**
	 * 生成Dao接口代码, 父接口默认为 BaseDao, 且为同一包下,
	 * 
	 * @param packageName
	 * @param className
	 * @return
	 */
	public static String generateDaoCode(String entityName, String packageName,
			String className) {
		StringBuffer sb = new StringBuffer(/* @TODO 版权声明 */);

		/* 包声明和类型导入 @TODO 参考 Entity生成类 */

		List<String> importTypes = new ArrayList<String>();
		importTypes.add(Util.ENTITY_PACKAGE + "." + entityName);

		sb.append("package " + packageName).append(";\n\n")
				.append(generateImport(importTypes)).append("\n");

		sb.append("public interface " + className);
		sb.append(" extends BaseDao\n");
		sb.append("{\n\n");

		sb.append(generateDaoInsertAndUpdate(entityName));

		sb.append("\n}");

		return sb.toString();
	}

	/**
	 * Dao接口中需要导入的类型, 通常包含:接口返回类型, 接口参数类型 1. 接口返回类型一般为对应的实体类的类型 XxxDao 返回类型为
	 * XxxInfo 或 XxxEntity 2. 接口参数类型
	 * 
	 * @param types
	 * @return
	 */
	private static String generateImport(final List<String> types) {
		StringBuffer importCodes = new StringBuffer();
		if (types == null)
			return importCodes.toString();

		for (String type : types) {
			importCodes.append("import " + type + ";\n");
		}

		return importCodes.toString();
	}

	/**
	 * 生成 DaoImpl 实现类代码, 父类默认为 BaseDaoImpl, 接口默认为 className + "Impl"
	 * 
	 * @param entityName
	 * @param packageName
	 * @return
	 */
	public static String generateDaoImplCode(String tableName,
			String packageName, final Map<String, String> properties) {

		String entityName = Util.getClassName(tableName);
		StringBuffer sb = new StringBuffer("public class ");
		sb.append(entityName + "DaoImpl");
		sb.append(" extends DaoImpl implements ");
		sb.append(entityName);
		sb.append("Dao\n{\n");

		// getTemplate(...)
		sb.append("\t/**\n\t* 实体属性赋值\n\t* @see I am auto generated by Jian\n\t*/\n\t@Override\n");
		sb.append("\tpublic Object getTemplate(ResultSet rs) throws SQLException\n\t{\n");
		sb.append("\t\t");
		sb.append(entityName);
		sb.append("Entity entity = new ");
		sb.append(entityName);
		sb.append("Entity();\n");
		sb.append(generateEntityAssignment(properties));
		sb.append("\t}\n");

		// insert(...)
		sb.append("\t/**\n\t* 简单记录插入\n\t* @see I am auto generated by Jian\n\t*/\n\t@Override\n");
		sb.append("\tpublic int insert(Object obj)\n\t{\n");
		sb.append("\t\t" + entityName + " entity = (" + entityName + ")obj;\n");
		sb.append("\t\tint intResult = -1;\n");
		sb.append(generateInserSql(tableName, properties));
		sb.append(generateDBParams(properties));
		sb.append(generateTryCatch());
		sb.append("\t}\n");

		// update(...) 暂不支持update的where条件
		sb.append("\t/**\n\t* 简单记录更新\n\t* @see I am auto generated by Jian\n\t*/\n\t@Override\n");
		sb.append("\tpublic int update(Object obj)\n\t{\n");
		sb.append("\t\t" + entityName + " entity = (" + entityName + ")obj;\n");
		sb.append("\t\tint intResult = -1;\n");
		sb.append(generateUpdateSql(tableName, properties));
		sb.append(generateDBParams(properties));
		sb.append(generateTryCatch());
		sb.append("\t}\n");

		sb.append("}");

		return sb.toString();
	}

	/**
	 * 
	 * 生成接口 insert 和 update 方法定义
	 * 
	 * @TODO 生成方法注释
	 * 
	 * @param entityName
	 * @return
	 */
	public static StringBuffer generateDaoInsertAndUpdate(String entityName) {
		StringBuffer result = new StringBuffer();
		result.append("\tint insert(" + entityName + " info);\n\n");
		result.append("\tint update(" + entityName + " info);\n");

		return result;
	}

	/**
	 * 生成 DaoImpl getTemplate 赋值部分代码
	 * 
	 * @param properties
	 * @return
	 */
	private static StringBuffer generateEntityAssignment(
			final Map<String, String> properties) {
		StringBuffer result = new StringBuffer();

		for (String property : properties.keySet()) {
			result.append("\t\tentity.set");

			result.append(Util.changeFirstToUpperCase(property));
			result.append("(rs.get");
			result.append(Util.changeFirstToUpperCase(properties.get(property)
					.split("\\.")[0]));
			result.append("(\"");
			result.append(Util.changeFirstToUpperCase(property));
			result.append("\"));\n");
		}

		result.append("\t\treturn entity;\n");

		return result;
	}

	/**
	 * 生成 INSERT SQL 语句
	 * 
	 * @param tableName
	 * @param properties
	 * @return
	 */
	private static StringBuffer generateInserSql(final String tableName,
			final Map<String, String> properties) {
		StringBuffer result = new StringBuffer();
		// String sqlText =
		// " INSERT INTO [tableName](Field,...) values (?,...); ";
		result.append("\t\tString sqlText = \" insert into ");
		result.append(tableName);
		result.append("(");
		for (String property : properties.keySet()) {
			result.append(" " + Util.changeFirstToUpperCase(property) + ",");
		}
		Util.deleteLastChar(",", result);
		result.append(" ) values (");
		for (int i = 0; i < properties.size(); i++) {
			result.append(" ?,");
		}
		Util.deleteLastChar(",", result);
		result.append(" );\";\n");

		return result;
	}

	/**
	 * 生成 UPDATE 语句 TODO 暂时不支持 where 条件的设置
	 * 
	 * @param tableName
	 * @param properties
	 * @return
	 */
	private static StringBuffer generateUpdateSql(final String tableName,
			final Map<String, String> properties) {
		StringBuffer result = new StringBuffer();
		// String sqlText =
		// " UPDATE [tableName] set Field=?,...) where xxx=? ";
		result.append("\t\tString sqlText = \" update ");
		result.append(tableName);
		result.append(" set ");
		for (String property : properties.keySet()) {
			result.append(" " + Util.changeFirstToUpperCase(property) + " = ?,");
		}
		Util.deleteLastChar(",", result);
		result.append(" where xxx = ?");
		result.append(" );\";\n");

		return result;
	}

	/**
	 * 生成 DBParams, 可用于 insert 、 update
	 * 
	 * @return
	 */
	private static StringBuffer generateDBParams(
			final Map<String, String> properties) {
		StringBuffer result = new StringBuffer();
		result.append("\t\tDBParamWrapper params = new DBParamWrapper();\n");
		for (String property : properties.keySet()) {
			result.append("\t\tparams.put(Types."
					+ Util.getSqlTypeName(properties.get(property).split("\\.")[0])
					+ ", entity.get" + Util.changeFirstToUpperCase(property)
					+ "());\n");
		}

		return result;
	}

	private static StringBuffer generateTryCatch() {
		StringBuffer result = new StringBuffer();
		result.append("\t\ttry\n\t\t{\n\t\t\tintResult = getDBHandler().executeNoneQuery(sqlText,params.getParams());\n\t\t}\n");
		result.append("\t\tcatch (SQLException e)\n\t\t{\n\t\te.printStackTrace();\n\t\t}\n");
		result.append("\t\treturn intResult;\n");

		return result;
	}
}
